package com.cuit.mimall.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cuit.mimall.common.R;
import com.cuit.mimall.dto.OrderDto;
import com.cuit.mimall.entity.Order;
import com.cuit.mimall.entity.OrderItem;
import com.cuit.mimall.entity.SeckillProduct;
import com.cuit.mimall.exception.ExceptionEnum;
import com.cuit.mimall.exception.XmException;
import com.cuit.mimall.mapper.OrderMapper;
import com.cuit.mimall.service.IOrderItemService;
import com.cuit.mimall.service.IOrderService;
import com.cuit.mimall.service.ISeckillProductService;
import com.cuit.mimall.util.IdWorker;
import com.cuit.mimall.util.RedisCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.cuit.mimall.util.RedisKey.SECKILL_PRODUCT_USER_LIST;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author TeaWu
 * @since 2023-07-02
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    private final IOrderItemService orderItemService;

    private final IdWorker idWorker;

    private final ISeckillProductService seckillProductService;

    private final RedisCache redisCache;

    @Autowired
    public OrderServiceImpl(IOrderItemService orderItemService, IdWorker idWorker, ISeckillProductService seckillProductService, RedisCache redisCache) {
        this.orderItemService = orderItemService;
        this.idWorker = idWorker;
        this.seckillProductService = seckillProductService;
        this.redisCache = redisCache;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<?> addOrder(Order order, List<OrderItem> items) {
        //保存订单,返回订单id
        boolean isOrderSaved = this.save(order);
        if (!isOrderSaved) {
            return R.error("订单保存失败");
        }
        for (OrderItem item : items) {
            item.setOrderId(order.getOrderId()); // 设置订单ID，假设item有setOrderId方法和order有getId方法
            boolean isItemSaved = orderItemService.save(item);
            if (!isItemSaved) {
                return R.error("订单项保存失败");
            }
        }
        return R.ok("订单保存成功", order.getOrderId());
    }

    /**
     * 根据用户ID获取订单
     *
     * @param userId   用户ID
     * @param pageNum  页码
     * @param pageSize 页大小
     * @return 订单结果
     */
    @Override
    public R<?> getOrders(Long userId, Integer pageNum, Integer pageSize) {
        Page<Order> page = new Page<>(pageNum, pageSize);
        IPage<Order> orderPage = baseMapper.selectPage(page, new LambdaQueryWrapper<Order>().eq(Order::getUserId, userId));

        List<Order> orders = orderPage.getRecords();

        if (orders.isEmpty()) {
            return R.ok("你没有订单", Collections.emptyList());
        }

        // 获取所有订单ID
        List<Long> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toList());

        // 一次性获取所有相关的 OrderItems 并以 orderId 分组存入 Map 中
        Map<Long, List<OrderItem>> itemsMap = orderItemService.list(new LambdaQueryWrapper<OrderItem>().in(OrderItem::getOrderId, orderIds))
                .stream().collect(Collectors.groupingBy(OrderItem::getOrderId));

        List<OrderDto> orderDtos = orders.stream().map(order -> {
            OrderDto orderDto = new OrderDto();
            orderDto.setOrder(order);
            // 直接从 Map 中获取 OrderItems
            orderDto.setItems(itemsMap.getOrDefault(order.getOrderId(), Collections.emptyList()));
            return orderDto;
        }).collect(Collectors.toList());

        return R.ok("订单列表", orderDtos);
    }

    /**
     * @param orderId 订单ID
     * @return R<?>   删除订单结果
     */
    @Override
    public R<?> deleteOrder(Long orderId) {
        //更新订单的del_flag字段为1
        Order order = new Order();
        order.setOrderId(orderId);
        order.setDelFlag(String.valueOf(1));
        boolean isOrderUpdated = this.updateById(order);
        if (!isOrderUpdated) {
            return R.error("订单删除失败");
        }
        return R.ok("订单删除成功");
    }

    /**
     * 用户支付订单
     *
     * @param orderId 订单ID
     * @return R<?>    支付订单结果
     */
    @Override
    public R<?> payOrder(Long orderId) {
        //这里可以调用支付接口，假设支付成功

        Order order = new Order();
        order.setOrderId(orderId);
        order.setStatus(String.valueOf(1));
        boolean isOrderUpdated = this.updateById(order);
        if (!isOrderUpdated) {
            return R.error("订单支付失败");
        }
        return R.ok("订单支付成功");
    }

    /**
     * 根据订单号和订单状态查询订单项
     *
     * @param pageNumber  页码
     * @param pageSize    每页数量
     * @param orderNo     订单号
     * @param orderStatus 订单状态
     */
    @Override
    public R<?> getOrderItemByCondition(Integer pageNumber, Integer pageSize, String orderNo, Integer orderStatus) {
        Page<Order> page = new Page<>(pageNumber, pageSize);
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        if (orderNo != null && !"".equals(orderNo)) {
            wrapper.eq(Order::getOrderId, orderNo);
        }
        if (orderStatus != null) {
            wrapper.eq(Order::getStatus, orderStatus);
        }
        try {
            IPage<Order> orderPage = baseMapper.selectPage(page, wrapper);
            if (orderPage.getTotal() == 0) {
                return R.ok("没有订单", Collections.emptyList());
            }
            return R.ok("订单列表", orderPage);
        } catch (Exception e) {
            log.error("查询订单项失败", e);
            return R.error("查询订单项失败");
        }
    }

    /**
     * 添加秒杀订单
     *
     * @param seckillId 秒杀商品id
     * @param userId    用户id
     */
    @Override
    public void addSeckillOrder(String seckillId, String userId) {
        // 订单id
        String orderId = String.valueOf(idWorker.nextId());
        // 商品id
        SeckillProduct seckillProduct = new SeckillProduct();
        seckillProduct.setSeckillId(Integer.parseInt(seckillId));
        SeckillProduct one = seckillProductService.getOne(seckillProduct);
        Integer productId = one.getProductId();
        // 秒杀价格
        Double price = (Double) one.getSeckillPrice();

        // 订单封装
        Order order = new Order();
        order.setOrderId(Long.valueOf(orderId));
        order.setUserId((long) Integer.parseInt(userId));
        order.setCreateTime(LocalDateTime.now());
        order.setTotalPrice(price);

        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(Long.valueOf(orderId));
        orderItem.setProductId(productId);
        orderItem.setQuantity(1);

        try {
            super.save(order);
            orderItemService.save(orderItem);
            // 减库存
            seckillProductService.decrStock(one.getSeckillId());
        } catch (Exception e) {
            e.printStackTrace();
            throw new XmException(ExceptionEnum.ADD_ORDER_ERROR);
        }

        // 订单创建成功, 将用户写入redis, 防止多次抢购
        redisCache.lPush(SECKILL_PRODUCT_USER_LIST + seckillId, userId);
    }
}
